package api

import (
	"crypto/md5"
	"encoding/hex"
	"net/http"
	"pd/server/com/errno"

	"github.com/gin-gonic/gin"
)

type PageResult struct {
	List  interface{} `json:"list"`
	Total int64       `json:"total"`
	Other interface{} `json:"other"`
}

type Response struct {
	Code      int         `json:"code"`
	Message   interface{} `json:"message"`
	RequestID string      `json:"requestid"`
	Data      interface{} `json:"data"`
}

func Ok(c *gin.Context, data interface{}) {
	SendResponse(c, nil, data, http.StatusOK)
}

func No(c *gin.Context, err error) {
	SendResponse(c, err, nil, http.StatusOK)
}

func Redirect(c *gin.Context, uri string) {
	c.Redirect(http.StatusFound, uri)
}

func NoWithMsg(c *gin.Context, msg string) {
	SendResponseWithMsgOrCode(c, 1000, nil, msg)
}

func NoWithMsgAndCode(c *gin.Context, msg string, code int) {
	SendResponseWithMsgOrCode(c, code, nil, msg)
}

func SendResponseWithMsgOrCode(c *gin.Context, code int, data interface{}, message string) {
	response := Response{
		Code:      code,
		Message:   message,
		Data:      data,
		RequestID: c.GetString("X-Request-ID"),
	}

	// always return http.StatusOK
	c.JSON(http.StatusOK, response)
}

func NoAbort(c *gin.Context, err error) {
	SendResponseAbort(c, err, nil)
}

func SendResponseAbort(c *gin.Context, err error, data interface{}) {
	SendResponse(c, err, data, http.StatusOK)
	c.Abort()
}

func SendResponse(c *gin.Context, err error, data interface{}, httpCode int) {
	code, message := errno.DecodeErr(err)

	response := Response{
		Code:      code,
		Message:   message,
		Data:      data,
		RequestID: c.GetString("X-Request-ID"),
	}

	// always return http.StatusOK
	c.JSON(httpCode, response)
}

// Changed the c.MustBindWith() ->  c.ShouldBindWith().
// I don't want to auto return 400 when error happened.
// origin function is here: https://github.com/gin-gonic/gin/blob/master/context.go
func Bind(c *gin.Context, form interface{}) (err error) {
	// err := c.MustBindWith(form, binding.Form)
	err = c.Bind(form)
	if err != nil {
		NoAbort(c, errno.New(errno.ErrBind, err).Add(err.Error()))
		return err
	}

	if len(c.Params) > 0 {
		err = c.BindUri(form)
		if err != nil {
			NoAbort(c, errno.New(errno.ErrBind, err).Add(err.Error()))
			return err
		}
	}

	return nil
}

//密码MD5加密
func MD5Str(password string) string {
	h := md5.New()
	h.Write([]byte(password)) // 需要加密的字符串
	md5Str := h.Sum(nil)
	return hex.EncodeToString(md5Str)
}
